package String;

import java.lang.reflect.Type;
import java.util.Arrays;

public class Test {

    public static void main1(String[] args) {
        //TODO 1.字符串构造:
        //String 是一个引用类型变量,和之前我们创建的类(自建的引用类型)
        String string = "xiabo";//这个是简写
        String string1 = new String("world");//这个是完整写法
        char[] array = {'a','b','c'};//字符数组
        String string2 = new String(array);//把字符数组合并成一个字符串
        System.out.println(string2);//因为String类重写了toString方法,那么就可以直接输出值而不是地址
        //TODO 对比字符串和普通类型的数组
        int[] a = {1,2,3,4};
        System.out.println(a.length);
        System.out.println(string.length());


    }
    public static void main2(String[] args) {
        //TODO 判断字符串是否是空的
        String str = "hello";
        System.out.println(str.isEmpty());//这个是判断字符串是不是空的
        System.out.println("==========");
        String str2 = "";
        System.out.println(str2.isEmpty());
        String str1 = null;//这个表示 str这个引用不指向任何对象
        //还可以这么求字符串长度
        System.out.println("hello".length());

    }


    public static void main3(String[] args) {
        //TODO 3.字符串对象的比较
        String str1 = new String("abcD");
        String str2 = new String("abcd");
        System.out.println(str2 == str1);//因为地址不一样所以是false
        //通过 equals来比较值一不一样
        System.out.println(str1.equals(str2));//这个调用的是String继承Object重写的equals方法
        System.out.println("=========");
        String str3 = "abcd";
        String str4 = "abcd";
        System.out.println(str3 == str4);//字符串常量池(存的是双引号引起来的字符串)会解释,堆中会有一个常量池,里面会保存没有的值,如果另一个变量也是这个值,就会把第一个常量池的值的地址给那个变量,因此地址就是一样的
        //s2 > s1 则返回正数
        //s2 = s1 则返回0
        //s2 < s1 则返回负数
        System.out.println(str2.compareTo(str1));
        //忽略大小写进行比较(验证码)
        System.out.println(str1.compareToIgnoreCase(str2));

    }

    public static void main4(String[] args) {
        //TODO 4.字符串查找
        //通过下标获取字符
        String s1 = "hello";
        char ch = s1.charAt(1);//获得1下标的值
        System.out.println(ch);
        //通过字符获取下标
        int index = s1.indexOf('l');//默认第一次出现的l
        System.out.println(index);
        int index1 = s1.indexOf('l',3);//从3下标开始
        System.out.println(index1);
        //也可以查询子串在主串的位置(kmp算法)
        String s2 = "ababcabcd";
        int index3 = s2.indexOf("abc",3);
        System.out.println(index3);
        //倒着找
        int index4 = s2.lastIndexOf("abc",4);//从4下标开始往后找
        System.out.println(index4);

    }


    public static void main5(String[] args) {
        //TODO 其他值和字符串的转换
        //数值转换成字符
        String s = String.valueOf(19.9);
        System.out.println(s);
        //字符串转化为其他值(也是引用类型)
        int data = Integer.parseInt("198");
        System.out.println(data);
        //字符串大小写转换
        String s1 = "hello";
        String ret = s1.toUpperCase();
        System.out.println(ret);//转变为大写,是一个新的对象不是在原来上改变
        String s2 = "Hello";
        ret = s2.toLowerCase();
        System.out.println(ret);
        //字符串转数组
        char[] array = s1.toCharArray();
        System.out.println(Arrays.toString(array));
        //数组转字符串
        char[] array1 = {'a','b','c'};
        String str1 = new String(array1);
        System.out.println(str1);
        //格式化输出
        s = String.format("%d-%d-%d",2019,9,29);
        System.out.println(s);

    }


    public static void main6(String[] args) {
        //TODO 字符串的替换
        String str = "ababcabcabababa";
        String ret = str.replace("ab","999");//所有的String操作都是产生一个新的对象
        System.out.println(ret);
        ret = str.replace('a','8');//只能替换单个,不能替换成多个
        System.out.println(ret);
        //替换第一个
        ret = str.replaceFirst("ab","ooo");
        System.out.println(ret);
        //替换所有的
        ret = str.replaceAll("ab","oo");
        System.out.println(ret);

    }

    public static void main7(String[] args) {
        //TODO 字符串的拆分
        String str = "hello abc world";
        String[] ret = str.split(" ");//以空格来分割
        System.out.println(ret);//这个打印的是地址
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }
        System.out.println("==========");
         ret = str.split(" ",2);//以空格来分割,分成俩份
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }
        System.out.println("==========");

        String s = "192.168.1.1";//以.等特殊符号,我们需要用转义字符
        ret = s.split("\\.");// \.才是一个点,\\.表示转义
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }
        System.out.println("==========");
        s = "192\\168\\1\\1";//以.等特殊符号,我们需要用转义字符
        ret = s.split("\\\\");//以俩个斜杠来分割
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }
        System.out.println("==========");
        s = "name=zhangsan&age=15";
        ret = s.split("=|&");//用|来实现多个分隔符的连接
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }
        System.out.println("==========");
         ret = s.split("&");//等价为上面
        for (int i = 0; i < ret.length; i++) {
            String x = ret[i];
            String[] ret2 = x.split("=");//可以在第一次的基础上进行第二次分割
            for (int j = 0; j < ret2.length; j++) {
                System.out.println(ret2[j]);
            }

        }

    }

    public static void main8(String[] args) {
        //TODO 截取字符串
        String str = "ababc";
        String ret = str.substring(0,3);//[0,3)
        System.out.println(ret);
        System.out.println("====");
        ret = str.substring(2);//从2下标开始
        System.out.println(ret);
        System.out.println("====");

    }

    public static void main9(String[] args) {
        //TODO 其他方法
        String ret;
        String str2 = "  sdfdsafd asffadg  ";
        System.out.println(str2);
        ret = str2.trim();
        System.out.println(ret);//去掉左右空格,中间无法去掉
        //关于为什么不能修改本身而是产生一个新对象,因为它的value是被private所修饰并且没有提供set和get方法
        final int[] a = {1,2,3};
        a[0] = 99;//可以修改
//        a = new int[10];被final修饰,则不可以
    }

    public static void main10(String[] args) {
    //TODO StringBuilde

//        String str = "hello";
//        str = str + "abc";
//        System.out.println(str);
        //等价于
        String str = "hello";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        stringBuilder.append("abc");
        str = stringBuilder.toString();
        System.out.println(str);
    }
    public static void main11(String[] args) {
        long start = System.currentTimeMillis();
        String s = "";
        for(int i = 0; i < 10000; ++i){
            s += i;//每次拼接会产生一个新的对象,所以会耗时
        }
        long end = System.currentTimeMillis();
        System.out.println("String: "+(end - start));
        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");//StringBuffer里面的append方法是被sychronized修饰的保证线程安全的方法,所有会比StringBuilder慢

        for(int i = 0; i < 10000; ++i){
            sbf.append(i);//直接在这个对象的后面拼接
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuffer: "+(end - start));
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();//不是线程安全的方法,所以快一点

        for(int i = 0; i < 10000; ++i){
            sbd.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuilder: "+(end - start));

    }

    public static void main12(String[] args) {
    //TODO StringBuilder 和 StringBuffer包含一些原先String没有的方法
        StringBuilder stringBuilder = new StringBuilder("hello");
        //直接逆转字符串
        stringBuilder.reverse();
        System.out.println(stringBuilder);
        //我们先来看三者的创建
        //String 和 他们俩的区别
        //1.后俩者是可变的,而String是不可变的
        //2. 包含的方法不一样
        String string = new String("xiaobao");
        StringBuilder stringBuilder1 = new StringBuilder("xiaohei");
        StringBuffer stringBuffer = new StringBuffer("xiaohuang");//这里看看源码
    }

}
